﻿/*! DataTables Foundation integration
 * ©2011-2015 SpryMedia Ltd - datatables.net/license
 */

/**
 * DataTables integration for Foundation. This requires Foundation 5 and
 * DataTables 1.10 or newer.
 *
 * This file sets the defaults and adds options to DataTables to style its
 * controls using Foundation. See http://datatables.net/manual/styling/foundation
 * for further information.
 */
(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery', 'datatables.net'], function ($) {
            return factory($, window, document);
        });
    }
    else if (typeof exports === 'object') {
        // CommonJS
        module.exports = function (root, $) {
            if (!root) {
                root = window;
            }

            if (!$ || !$.fn.dataTable) {
                $ = require('datatables.net')(root, $).$;
            }

            return factory($, root, root.document);
        };
    }
    else {
        // Browser
        factory(jQuery, window, document);
    }
}(function ($, window, document, undefined) {
    'use strict';
    var DataTable = $.fn.dataTable;


    $.extend(DataTable.ext.classes, {
        sWrapper: "dataTables_wrapper dt-foundation",
        sProcessing: "dataTables_processing panel"
    });


    /* Set the defaults for DataTables initialisation */
    $.extend(true, DataTable.defaults, {
        dom:
            "<'row'<'small-6 columns'l><'small-6 columns'f>r>" +
            "t" +
            "<'row'<'small-6 columns'i><'small-6 columns'p>>",
        renderer: 'foundation'
    });


    /* Page button renderer */
    DataTable.ext.renderer.pageButton.foundation = function (settings, host, idx, buttons, page, pages) {
        var api = new DataTable.Api(settings);
        var classes = settings.oClasses;
        var lang = settings.oLanguage.oPaginate;
        var aria = settings.oLanguage.oAria.paginate || {};
        var btnDisplay, btnClass;

        var attach = function (container, buttons) {
            var i, ien, node, button;
            var clickHandler = function (e) {
                e.preventDefault();
                if (!$(e.currentTarget).hasClass('unavailable') && api.page() != e.data.action) {
                    api.page(e.data.action).draw('page');
                }
            };

            for (i = 0, ien = buttons.length ; i < ien ; i++) {
                button = buttons[i];

                if ($.isArray(button)) {
                    attach(container, button);
                }
                else {
                    btnDisplay = '';
                    btnClass = '';

                    switch (button) {
                        case 'ellipsis':
                            btnDisplay = '&#x2026;';
                            btnClass = 'unavailable';
                            break;

                        case 'first':
                            btnDisplay = lang.sFirst;
                            btnClass = button + (page > 0 ?
                                '' : ' unavailable');
                            break;

                        case 'previous':
                            btnDisplay = lang.sPrevious;
                            btnClass = button + (page > 0 ?
                                '' : ' unavailable');
                            break;

                        case 'next':
                            btnDisplay = lang.sNext;
                            btnClass = button + (page < pages - 1 ?
                                '' : ' unavailable');
                            break;

                        case 'last':
                            btnDisplay = lang.sLast;
                            btnClass = button + (page < pages - 1 ?
                                '' : ' unavailable');
                            break;

                        default:
                            btnDisplay = button + 1;
                            btnClass = page === button ?
                                'current' : '';
                            break;
                    }

                    if (btnDisplay) {
                        node = $('<li>', {
                            'class': classes.sPageButton + ' ' + btnClass,
                            'aria-controls': settings.sTableId,
                            'aria-label': aria[button],
                            'tabindex': settings.iTabIndex,
                            'id': idx === 0 && typeof button === 'string' ?
								settings.sTableId + '_' + button :
								null
                        })
                            .append($('<a>', {
                                'href': '#'
                            })
                                .html(btnDisplay)
                            )
                            .appendTo(container);

                        settings.oApi._fnBindAction(
                            node, { action: button }, clickHandler
                        );
                    }
                }
            }
        };

        attach(
            $(host).empty().html('<ul class="pagination"/>').children('ul'),
            buttons
        );
    };


    return DataTable;
}));





/*! Responsive 2.0.0
 * 2014-2015 SpryMedia Ltd - datatables.net/license
 */

/**
 * @summary     Responsive
 * @description Responsive tables plug-in for DataTables
 * @version     2.0.0
 * @file        dataTables.responsive.js
 * @author      SpryMedia Ltd (www.sprymedia.co.uk)
 * @contact     www.sprymedia.co.uk/contact
 * @copyright   Copyright 2014-2015 SpryMedia Ltd.
 *
 * This source file is free software, available under the following license:
 *   MIT license - http://datatables.net/license/mit
 *
 * This source file is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
 *
 * For details please refer to: http://www.datatables.net
 */
(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery', 'datatables.net'], function ($) {
            return factory($, window, document);
        });
    }
    else if (typeof exports === 'object') {
        // CommonJS
        module.exports = function (root, $) {
            if (!root) {
                root = window;
            }

            if (!$ || !$.fn.dataTable) {
                $ = require('datatables.net')(root, $).$;
            }

            return factory($, root, root.document);
        };
    }
    else {
        // Browser
        factory(jQuery, window, document);
    }
}(function ($, window, document, undefined) {
    'use strict';
    var DataTable = $.fn.dataTable;


    /**
     * Responsive is a plug-in for the DataTables library that makes use of
     * DataTables' ability to change the visibility of columns, changing the
     * visibility of columns so the displayed columns fit into the table container.
     * The end result is that complex tables will be dynamically adjusted to fit
     * into the viewport, be it on a desktop, tablet or mobile browser.
     *
     * Responsive for DataTables has two modes of operation, which can used
     * individually or combined:
     *
     * * Class name based control - columns assigned class names that match the
     *   breakpoint logic can be shown / hidden as required for each breakpoint.
     * * Automatic control - columns are automatically hidden when there is no
     *   room left to display them. Columns removed from the right.
     *
     * In additional to column visibility control, Responsive also has built into
     * options to use DataTables' child row display to show / hide the information
     * from the table that has been hidden. There are also two modes of operation
     * for this child row display:
     *
     * * Inline - when the control element that the user can use to show / hide
     *   child rows is displayed inside the first column of the table.
     * * Column - where a whole column is dedicated to be the show / hide control.
     *
     * Initialisation of Responsive is performed by:
     *
     * * Adding the class `responsive` or `dt-responsive` to the table. In this case
     *   Responsive will automatically be initialised with the default configuration
     *   options when the DataTable is created.
     * * Using the `responsive` option in the DataTables configuration options. This
     *   can also be used to specify the configuration options, or simply set to
     *   `true` to use the defaults.
     *
     *  @class
     *  @param {object} settings DataTables settings object for the host table
     *  @param {object} [opts] Configuration options
     *  @requires jQuery 1.7+
     *  @requires DataTables 1.10.3+
     *
     *  @example
     *      $('#example').DataTable( {
     *        responsive: true
     *      } );
     *    } );
     */
    var Responsive = function (settings, opts) {
        // Sanity check that we are using DataTables 1.10 or newer
        if (!DataTable.versionCheck || !DataTable.versionCheck('1.10.3')) {
            throw 'DataTables Responsive requires DataTables 1.10.3 or newer';
        }

        this.s = {
            dt: new DataTable.Api(settings),
            columns: [],
            current: []
        };

        // Check if responsive has already been initialised on this table
        if (this.s.dt.settings()[0].responsive) {
            return;
        }

        // details is an object, but for simplicity the user can give it as a string
        if (opts && typeof opts.details === 'string') {
            opts.details = { type: opts.details };
        }

        this.c = $.extend(true, {}, Responsive.defaults, DataTable.defaults.responsive, opts);
        settings.responsive = this;
        this._constructor();
    };

    $.extend(Responsive.prototype, {
        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
         * Constructor
         */

        /**
         * Initialise the Responsive instance
         *
         * @private
         */
        _constructor: function () {
            var that = this;
            var dt = this.s.dt;
            var dtPrivateSettings = dt.settings()[0];

            dt.settings()[0]._responsive = this;

            // Use DataTables' throttle function to avoid processor thrashing on
            // resize
            $(window).on('resize.dtr orientationchange.dtr', DataTable.util.throttle(function () {
                that._resize();
            }));

            // DataTables doesn't currently trigger an event when a row is added, so
            // we need to hook into its private API to enforce the hidden rows when
            // new data is added
            dtPrivateSettings.oApi._fnCallbackReg(dtPrivateSettings, 'aoRowCreatedCallback', function (tr, data, idx) {
                if ($.inArray(false, that.s.current) !== -1) {
                    $('td, th', tr).each(function (i) {
                        var idx = dt.column.index('toData', i);

                        if (that.s.current[idx] === false) {
                            $(this).css('display', 'none');
                        }
                    });
                }
            });

            // Destroy event handler
            dt.on('destroy.dtr', function () {
                dt.off('.dtr');
                $(dt.table().body()).off('.dtr');
                $(window).off('resize.dtr orientationchange.dtr');

                // Restore the columns that we've hidden
                $.each(that.s.current, function (i, val) {
                    if (val === false) {
                        that._setColumnVis(i, true);
                    }
                });
            });

            // Reorder the breakpoints array here in case they have been added out
            // of order
            this.c.breakpoints.sort(function (a, b) {
                return a.width < b.width ? 1 :
                    a.width > b.width ? -1 : 0;
            });

            this._classLogic();
            this._resizeAuto();

            // Details handler
            var details = this.c.details;
            if (details.type !== false) {
                that._detailsInit();

                // DataTables will trigger this event on every column it shows and
                // hides individually
                dt.on('column-visibility.dtr', function (e, ctx, col, vis) {
                    that._classLogic();
                    that._resizeAuto();
                    that._resize();
                });

                // Redraw the details box on each draw which will happen if the data
                // has changed. This is used until DataTables implements a native
                // `updated` event for rows
                dt.on('draw.dtr', function () {
                    that._redrawChildren();
                });

                $(dt.table().node()).addClass('dtr-' + details.type);
            }

            dt.on('column-reorder.dtr', function (e, settings, details) {
                // This requires ColReorder 1.2.1 or newer
                if (details.drop) {
                    that._classLogic();
                    that._resizeAuto();
                    that._resize();
                }
            });

            // First pass - draw the table for the current viewport size
            this._resize();
        },


        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
         * Private methods
         */

        /**
         * Calculate the visibility for the columns in a table for a given
         * breakpoint. The result is pre-determined based on the class logic if
         * class names are used to control all columns, but the width of the table
         * is also used if there are columns which are to be automatically shown
         * and hidden.
         *
         * @param  {string} breakpoint Breakpoint name to use for the calculation
         * @return {array} Array of boolean values initiating the visibility of each
         *   column.
         *  @private
         */
        _columnsVisiblity: function (breakpoint) {
            var dt = this.s.dt;
            var columns = this.s.columns;
            var i, ien;

            // Create an array that defines the column ordering based first on the
            // column's priority, and secondly the column index. This allows the
            // columns to be removed from the right if the priority matches
            var order = columns
                .map(function (col, idx) {
                    return {
                        columnIdx: idx,
                        priority: col.priority
                    };
                })
                .sort(function (a, b) {
                    if (a.priority !== b.priority) {
                        return a.priority - b.priority;
                    }
                    return a.columnIdx - b.columnIdx;
                });


            // Class logic - determine which columns are in this breakpoint based
            // on the classes. If no class control (i.e. `auto`) then `-` is used
            // to indicate this to the rest of the function
            var display = $.map(columns, function (col) {
                return col.auto && col.minWidth === null ?
                    false :
                    col.auto === true ?
                        '-' :
                        $.inArray(breakpoint, col.includeIn) !== -1;
            });

            // Auto column control - first pass: how much width is taken by the
            // ones that must be included from the non-auto columns
            var requiredWidth = 0;
            for (i = 0, ien = display.length ; i < ien ; i++) {
                if (display[i] === true) {
                    requiredWidth += columns[i].minWidth;
                }
            }

            // Second pass, use up any remaining width for other columns. For
            // scrolling tables we need to subtract the width of the scrollbar. It
            // may not be requires which makes this sub-optimal, but it would
            // require another full redraw to make complete use of those extra few
            // pixels
            var scrolling = dt.settings()[0].oScroll;
            var bar = scrolling.sY || scrolling.sX ? scrolling.iBarWidth : 0;
            var widthAvailable = dt.table().container().offsetWidth - bar;
            var usedWidth = widthAvailable - requiredWidth;

            // Control column needs to always be included. This makes it sub-
            // optimal in terms of using the available with, but to stop layout
            // thrashing or overflow. Also we need to account for the control column
            // width first so we know how much width is available for the other
            // columns, since the control column might not be the first one shown
            for (i = 0, ien = display.length ; i < ien ; i++) {
                if (columns[i].control) {
                    usedWidth -= columns[i].minWidth;
                }
            }

            // Allow columns to be shown (counting by priority and then right to
            // left) until we run out of room
            var empty = false;
            for (i = 0, ien = order.length ; i < ien ; i++) {
                var colIdx = order[i].columnIdx;

                if (display[colIdx] === '-' && !columns[colIdx].control && columns[colIdx].minWidth) {
                    // Once we've found a column that won't fit we don't let any
                    // others display either, or columns might disappear in the
                    // middle of the table
                    if (empty || usedWidth - columns[colIdx].minWidth < 0) {
                        empty = true;
                        display[colIdx] = false;
                    }
                    else {
                        display[colIdx] = true;
                    }

                    usedWidth -= columns[colIdx].minWidth;
                }
            }

            // Determine if the 'control' column should be shown (if there is one).
            // This is the case when there is a hidden column (that is not the
            // control column). The two loops look inefficient here, but they are
            // trivial and will fly through. We need to know the outcome from the
            // first , before the action in the second can be taken
            var showControl = false;

            for (i = 0, ien = columns.length ; i < ien ; i++) {
                if (!columns[i].control && !columns[i].never && !display[i]) {
                    showControl = true;
                    break;
                }
            }

            for (i = 0, ien = columns.length ; i < ien ; i++) {
                if (columns[i].control) {
                    display[i] = showControl;
                }
            }

            // Finally we need to make sure that there is at least one column that
            // is visible
            if ($.inArray(true, display) === -1) {
                display[0] = true;
            }

            return display;
        },


        /**
         * Create the internal `columns` array with information about the columns
         * for the table. This includes determining which breakpoints the column
         * will appear in, based upon class names in the column, which makes up the
         * vast majority of this method.
         *
         * @private
         */
        _classLogic: function () {
            var that = this;
            var calc = {};
            var breakpoints = this.c.breakpoints;
            var dt = this.s.dt;
            var columns = dt.columns().eq(0).map(function (i) {
                var column = this.column(i);
                var className = column.header().className;
                var priority = dt.settings()[0].aoColumns[i].responsivePriority;

                if (priority === undefined) {
                    priority = $(column.header).data('priority') !== undefined ?
                        $(column.header).data('priority') * 1 :
                        10000;
                }

                return {
                    className: className,
                    includeIn: [],
                    auto: false,
                    control: false,
                    never: className.match(/\bnever\b/) ? true : false,
                    priority: priority
                };
            });

            // Simply add a breakpoint to `includeIn` array, ensuring that there are
            // no duplicates
            var add = function (colIdx, name) {
                var includeIn = columns[colIdx].includeIn;

                if ($.inArray(name, includeIn) === -1) {
                    includeIn.push(name);
                }
            };

            var column = function (colIdx, name, operator, matched) {
                var size, i, ien;

                if (!operator) {
                    columns[colIdx].includeIn.push(name);
                }
                else if (operator === 'max-') {
                    // Add this breakpoint and all smaller
                    size = that._find(name).width;

                    for (i = 0, ien = breakpoints.length ; i < ien ; i++) {
                        if (breakpoints[i].width <= size) {
                            add(colIdx, breakpoints[i].name);
                        }
                    }
                }
                else if (operator === 'min-') {
                    // Add this breakpoint and all larger
                    size = that._find(name).width;

                    for (i = 0, ien = breakpoints.length ; i < ien ; i++) {
                        if (breakpoints[i].width >= size) {
                            add(colIdx, breakpoints[i].name);
                        }
                    }
                }
                else if (operator === 'not-') {
                    // Add all but this breakpoint
                    for (i = 0, ien = breakpoints.length ; i < ien ; i++) {
                        if (breakpoints[i].name.indexOf(matched) === -1) {
                            add(colIdx, breakpoints[i].name);
                        }
                    }
                }
            };

            // Loop over each column and determine if it has a responsive control
            // class
            columns.each(function (col, i) {
                var classNames = col.className.split(' ');
                var hasClass = false;

                // Split the class name up so multiple rules can be applied if needed
                for (var k = 0, ken = classNames.length ; k < ken ; k++) {
                    var className = $.trim(classNames[k]);

                    if (className === 'all') {
                        // Include in all
                        hasClass = true;
                        col.includeIn = $.map(breakpoints, function (a) {
                            return a.name;
                        });
                        return;
                    }
                    else if (className === 'none' || col.never) {
                        // Include in none (default) and no auto
                        hasClass = true;
                        return;
                    }
                    else if (className === 'control') {
                        // Special column that is only visible, when one of the other
                        // columns is hidden. This is used for the details control
                        hasClass = true;
                        col.control = true;
                        return;
                    }

                    $.each(breakpoints, function (j, breakpoint) {
                        // Does this column have a class that matches this breakpoint?
                        var brokenPoint = breakpoint.name.split('-');
                        var re = new RegExp('(min\\-|max\\-|not\\-)?(' + brokenPoint[0] + ')(\\-[_a-zA-Z0-9])?');
                        var match = className.match(re);

                        if (match) {
                            hasClass = true;

                            if (match[2] === brokenPoint[0] && match[3] === '-' + brokenPoint[1]) {
                                // Class name matches breakpoint name fully
                                column(i, breakpoint.name, match[1], match[2] + match[3]);
                            }
                            else if (match[2] === brokenPoint[0] && !match[3]) {
                                // Class name matched primary breakpoint name with no qualifier
                                column(i, breakpoint.name, match[1], match[2]);
                            }
                        }
                    });
                }

                // If there was no control class, then automatic sizing is used
                if (!hasClass) {
                    col.auto = true;
                }
            });

            this.s.columns = columns;
        },


        /**
         * Show the details for the child row
         *
         * @param  {DataTables.Api} row    API instance for the row
         * @param  {boolean}        update Update flag
         * @private
         */
        _detailsDisplay: function (row, update) {
            var that = this;
            var dt = this.s.dt;

            var res = this.c.details.display(row, update, function () {
                return that.c.details.renderer(
                    dt, row[0], that._detailsObj(row[0])
                );
            });

            if (res === true || res === false) {
                $(dt.table().node()).triggerHandler('responsive-display.dt', [dt, row, res, update]);
            }
        },


        /**
         * Initialisation for the details handler
         *
         * @private
         */
        _detailsInit: function () {
            var that = this;
            var dt = this.s.dt;
            var details = this.c.details;

            // The inline type always uses the first child as the target
            if (details.type === 'inline') {
                details.target = 'td:first-child';
            }

            // Keyboard accessibility
            dt.on('draw.dtr', function () {
                that._tabIndexes();
            });
            that._tabIndexes(); // Initial draw has already happened

            $(dt.table().body()).on('keyup.dtr', 'td', function (e) {
                if (e.keyCode === 13 && $(this).data('dtr-keyboard')) {
                    $(this).click();
                }
            });

            // type.target can be a string jQuery selector or a column index
            var target = details.target;
            var selector = typeof target === 'string' ? target : 'td';

            // Click handler to show / hide the details rows when they are available
            $(dt.table().body())
                .on('mousedown.dtr', selector, function (e) {
                    // For mouse users, prevent the focus ring from showing
                    e.preventDefault();
                })
                .on('click.dtr', selector, function () {
                    // If the table is not collapsed (i.e. there is no hidden columns)
                    // then take no action
                    if (!$(dt.table().node()).hasClass('collapsed')) {
                        return;
                    }

                    // Check that the row is actually a DataTable's controlled node
                    if (!dt.row($(this).closest('tr')).length) {
                        return;
                    }

                    // For column index, we determine if we should act or not in the
                    // handler - otherwise it is already okay
                    if (typeof target === 'number') {
                        var targetIdx = target < 0 ?
                            dt.columns().eq(0).length + target :
                            target;

                        if (dt.cell(this).index().column !== targetIdx) {
                            return;
                        }
                    }

                    // $().closest() includes itself in its check
                    var row = dt.row($(this).closest('tr'));

                    // The renderer is given as a function so the caller can execute it
                    // only when they need (i.e. if hiding there is no point is running
                    // the renderer)
                    that._detailsDisplay(row, false);
                });
        },


        /**
         * Get the details to pass to a renderer for a row
         * @param  {int} rowIdx Row index
         * @private
         */
        _detailsObj: function (rowIdx) {
            var that = this;
            var dt = this.s.dt;

            return $.map(this.s.columns, function (col, i) {
                if (col.never) {
                    return;
                }

                return {
                    title: dt.settings()[0].aoColumns[i].sTitle,
                    data: dt.cell(rowIdx, i).render(that.c.orthogonal),
                    hidden: dt.column(i).visible() && !that.s.current[i]
                };
            });
        },


        /**
         * Find a breakpoint object from a name
         *
         * @param  {string} name Breakpoint name to find
         * @return {object}      Breakpoint description object
         * @private
         */
        _find: function (name) {
            var breakpoints = this.c.breakpoints;

            for (var i = 0, ien = breakpoints.length ; i < ien ; i++) {
                if (breakpoints[i].name === name) {
                    return breakpoints[i];
                }
            }
        },


        /**
         * Re-create the contents of the child rows as the display has changed in
         * some way.
         *
         * @private
         */
        _redrawChildren: function () {
            var that = this;
            var dt = this.s.dt;

            dt.rows({ page: 'current' }).iterator('row', function (settings, idx) {
                var row = dt.row(idx);

                that._detailsDisplay(dt.row(idx), true);
            });
        },


        /**
         * Alter the table display for a resized viewport. This involves first
         * determining what breakpoint the window currently is in, getting the
         * column visibilities to apply and then setting them.
         *
         * @private
         */
        _resize: function () {
            var that = this;
            var dt = this.s.dt;
            var width = $(window).width();
            var breakpoints = this.c.breakpoints;
            var breakpoint = breakpoints[0].name;
            var columns = this.s.columns;
            var i, ien;
            var oldVis = this.s.current.slice();

            // Determine what breakpoint we are currently at
            for (i = breakpoints.length - 1 ; i >= 0 ; i--) {
                if (width <= breakpoints[i].width) {
                    breakpoint = breakpoints[i].name;
                    break;
                }
            }

            // Show the columns for that break point
            var columnsVis = this._columnsVisiblity(breakpoint);
            this.s.current = columnsVis;

            // Set the class before the column visibility is changed so event
            // listeners know what the state is. Need to determine if there are
            // any columns that are not visible but can be shown
            var collapsedClass = false;
            for (i = 0, ien = columns.length ; i < ien ; i++) {
                if (columnsVis[i] === false && !columns[i].never) {
                    collapsedClass = true;
                    break;
                }
            }

            $(dt.table().node()).toggleClass('collapsed', collapsedClass);

            var changed = false;

            dt.columns().eq(0).each(function (colIdx, i) {
                if (columnsVis[i] !== oldVis[i]) {
                    changed = true;
                    that._setColumnVis(colIdx, columnsVis[i]);
                }
            });

            if (changed) {
                this._redrawChildren();
            }
        },


        /**
         * Determine the width of each column in the table so the auto column hiding
         * has that information to work with. This method is never going to be 100%
         * perfect since column widths can change slightly per page, but without
         * seriously compromising performance this is quite effective.
         *
         * @private
         */
        _resizeAuto: function () {
            var dt = this.s.dt;
            var columns = this.s.columns;

            // Are we allowed to do auto sizing?
            if (!this.c.auto) {
                return;
            }

            // Are there any columns that actually need auto-sizing, or do they all
            // have classes defined
            if ($.inArray(true, $.map(columns, function (c) { return c.auto; })) === -1) {
                return;
            }

            // Clone the table with the current data in it
            var tableWidth = dt.table().node().offsetWidth;
            var columnWidths = dt.columns;
            var clonedTable = dt.table().node().cloneNode(false);
            var clonedHeader = $(dt.table().header().cloneNode(false)).appendTo(clonedTable);
            var clonedBody = $(dt.table().body().cloneNode(false)).appendTo(clonedTable);

            // Header
            var headerCells = dt.columns()
                .header()
                .filter(function (idx) {
                    return dt.column(idx).visible();
                })
                .to$()
                .clone(false)
                .css('display', 'table-cell');

            // Body rows - we don't need to take account of DataTables' column
            // visibility since we implement our own here (hence the `display` set)
            $(clonedBody)
                .append($(dt.rows({ page: 'current' }).nodes()).clone(false))
                .find('th, td').css('display', '');

            // Footer
            var footer = dt.table().footer();
            if (footer) {
                var clonedFooter = $(footer.cloneNode(false)).appendTo(clonedTable);
                var footerCells = dt.columns()
                    .header()
                    .filter(function (idx) {
                        return dt.column(idx).visible();
                    })
                    .to$()
                    .clone(false)
                    .css('display', 'table-cell');

                $('<tr/>')
                    .append(footerCells)
                    .appendTo(clonedFooter);
            }

            $('<tr/>')
                .append(headerCells)
                .appendTo(clonedHeader);

            // In the inline case extra padding is applied to the first column to
            // give space for the show / hide icon. We need to use this in the
            // calculation
            if (this.c.details.type === 'inline') {
                $(clonedTable).addClass('dtr-inline collapsed');
            }

            var inserted = $('<div/>')
                .css({
                    width: 1,
                    height: 1,
                    overflow: 'hidden'
                })
                .append(clonedTable);

            inserted.insertBefore(dt.table().node());

            // The cloned header now contains the smallest that each column can be
            headerCells.each(function (i) {
                var idx = dt.column.index('fromVisible', i);
                columns[idx].minWidth = this.offsetWidth || 0;
            });

            inserted.remove();
        },

        /**
         * Set a column's visibility.
         *
         * We don't use DataTables' column visibility controls in order to ensure
         * that column visibility can Responsive can no-exist. Since only IE8+ is
         * supported (and all evergreen browsers of course) the control of the
         * display attribute works well.
         *
         * @param {integer} col      Column index
         * @param {boolean} showHide Show or hide (true or false)
         * @private
         */
        _setColumnVis: function (col, showHide) {
            var dt = this.s.dt;
            var display = showHide ? '' : 'none'; // empty string will remove the attr

            $(dt.column(col).header()).css('display', display);
            $(dt.column(col).footer()).css('display', display);
            dt.column(col).nodes().to$().css('display', display);
        },


        /**
         * Update the cell tab indexes for keyboard accessibility. This is called on
         * every table draw - that is potentially inefficient, but also the least
         * complex option given that column visibility can change on the fly. Its a
         * shame user-focus was removed from CSS 3 UI, as it would have solved this
         * issue with a single CSS statement.
         *
         * @private
         */
        _tabIndexes: function () {
            var dt = this.s.dt;
            var cells = dt.cells({ page: 'current' }).nodes().to$();
            var ctx = dt.settings()[0];
            var target = this.c.details.target;

            cells.filter('[data-dtr-keyboard]').removeData('[data-dtr-keyboard]');

            var selector = typeof target === 'number' ?
                ':eq(' + target + ')' :
                target;

            $(selector, dt.rows({ page: 'current' }).nodes())
                .attr('tabIndex', ctx.iTabIndex)
                .data('dtr-keyboard', 1);
        }
    });


    /**
     * List of default breakpoints. Each item in the array is an object with two
     * properties:
     *
     * * `name` - the breakpoint name.
     * * `width` - the breakpoint width
     *
     * @name Responsive.breakpoints
     * @static
     */
    Responsive.breakpoints = [
        { name: 'desktop', width: Infinity },
        { name: 'tablet-l', width: 1024 },
        { name: 'tablet-p', width: 768 },
        { name: 'mobile-l', width: 480 },
        { name: 'mobile-p', width: 320 }
    ];


    /**
     * Display methods - functions which define how the hidden data should be shown
     * in the table.
     *
     * @namespace
     * @name Responsive.defaults
     * @static
     */
    Responsive.display = {
        childRow: function (row, update, render) {
            if (update) {
                if ($(row.node()).hasClass('parent')) {
                    row.child(render(), 'child').show();

                    return true;
                }
            }
            else {
                if (!row.child.isShown()) {
                    row.child(render(), 'child').show();
                    $(row.node()).addClass('parent');

                    return true;
                }
                else {
                    row.child(false);
                    $(row.node()).removeClass('parent');

                    return false;
                }
            }
        },

        childRowImmediate: function (row, update, render) {
            if ((!update && row.child.isShown()) || !row.responsive.hasHidden()) {
                // User interaction and the row is show, or nothing to show
                row.child(false);
                $(row.node()).removeClass('parent');

                return false;
            }
            else {
                // Display
                row.child(render(), 'child').show();
                $(row.node()).addClass('parent');

                return true;
            }
        },

        // This is a wrapper so the modal options for Bootstrap and jQuery UI can
        // have options passed into them. This specific one doesn't need to be a
        // function but it is for consistency in the `modal` name
        modal: function (options) {
            return function (row, update, render) {
                if (!update) {
                    // Show a modal
                    var close = function () {
                        modal.remove(); // will tidy events for us
                        $(document).off('keypress.dtr');
                    };

                    var modal = $('<div class="dtr-modal"/>')
                        .append($('<div class="dtr-modal-display"/>')
                            .append($('<div class="dtr-modal-content"/>')
                                .append(render())
                            )
                            .append($('<div class="dtr-modal-close">&times;</div>')
                                .click(function () {
                                    close();
                                })
                            )
                        )
                        .append($('<div class="dtr-modal-background"/>')
                            .click(function () {
                                close();
                            })
                        )
                        .appendTo('body');

                    if (options && options.header) {
                        modal.find('div.dtr-modal-content').prepend(
                            '<h2>' + options.header(row) + '</h2>'
                        );
                    }

                    $(document).on('keyup.dtr', function (e) {
                        if (e.keyCode === 27) {
                            e.stopPropagation();

                            close();
                        }
                    });
                }
                else {
                    $('div.dtr-modal-content')
                        .empty()
                        .append(render());
                }
            };
        }
    };


    /**
     * Responsive default settings for initialisation
     *
     * @namespace
     * @name Responsive.defaults
     * @static
     */
    Responsive.defaults = {
        /**
         * List of breakpoints for the instance. Note that this means that each
         * instance can have its own breakpoints. Additionally, the breakpoints
         * cannot be changed once an instance has been creased.
         *
         * @type {Array}
         * @default Takes the value of `Responsive.breakpoints`
         */
        breakpoints: Responsive.breakpoints,

        /**
         * Enable / disable auto hiding calculations. It can help to increase
         * performance slightly if you disable this option, but all columns would
         * need to have breakpoint classes assigned to them
         *
         * @type {Boolean}
         * @default  `true`
         */
        auto: true,

        /**
         * Details control. If given as a string value, the `type` property of the
         * default object is set to that value, and the defaults used for the rest
         * of the object - this is for ease of implementation.
         *
         * The object consists of the following properties:
         *
         * * `display` - A function that is used to show and hide the hidden details
         * * `renderer` - function that is called for display of the child row data.
         *   The default function will show the data from the hidden columns
         * * `target` - Used as the selector for what objects to attach the child
         *   open / close to
         * * `type` - `false` to disable the details display, `inline` or `column`
         *   for the two control types
         *
         * @type {Object|string}
         */
        details: {
            display: Responsive.display.childRow,

            renderer: function (api, rowIdx, columns) {
                var data = $.map(columns, function (col, i) {
                    return col.hidden ?
                        '<li data-dtr-index="' + i + '">' +
                            '<span class="dtr-title">' +
                                col.title + ':' +
                            '</span> ' +
                            '<span class="dtr-data">' +
                                col.data +
                            '</span>' +
                        '</li>' :
                        '';
                }).join('');

                return data ?
                    $('<ul data-dtr-index="' + rowIdx + '"/>').append(data) :
                    false;
            },

            target: 0,

            type: 'inline'
        },

        /**
         * Orthogonal data request option. This is used to define the data type
         * requested when Responsive gets the data to show in the child row.
         *
         * @type {String}
         */
        orthogonal: 'display'
    };


    /*
     * API
     */
    var Api = $.fn.dataTable.Api;

    // Doesn't do anything - work around for a bug in DT... Not documented
    Api.register('responsive()', function () {
        return this;
    });

    Api.register('responsive.index()', function (li) {
        li = $(li);

        return {
            column: li.data('dtr-index'),
            row: li.parent().data('dtr-index')
        };
    });

    Api.register('responsive.rebuild()', function () {
        return this.iterator('table', function (ctx) {
            if (ctx._responsive) {
                ctx._responsive._classLogic();
            }
        });
    });

    Api.register('responsive.recalc()', function () {
        return this.iterator('table', function (ctx) {
            if (ctx._responsive) {
                ctx._responsive._resizeAuto();
                ctx._responsive._resize();
            }
        });
    });

    Api.register('responsive.hasHidden()', function () {
        var ctx = this.context[0];

        return ctx._responsive ?
            $.inArray(false, ctx._responsive.s.current) !== -1 :
            false;
    });


    /**
     * Version information
     *
     * @name Responsive.version
     * @static
     */
    Responsive.version = '2.0.0';


    $.fn.dataTable.Responsive = Responsive;
    $.fn.DataTable.Responsive = Responsive;

    // Attach a listener to the document which listens for DataTables initialisation
    // events so we can automatically initialise
    $(document).on('init.dt.dtr', function (e, settings, json) {
        if (e.namespace !== 'dt') {
            return;
        }

        if ($(settings.nTable).hasClass('responsive') ||
             $(settings.nTable).hasClass('dt-responsive') ||
             settings.oInit.responsive ||
             DataTable.defaults.responsive
        ) {
            var init = settings.oInit.responsive;

            if (init !== false) {
                new Responsive(settings, $.isPlainObject(init) ? init : {});
            }
        }
    });


    return Responsive;
}));




jQuery.fn.dataTableExt.oApi.fnReloadAjax = function (oSettings, sNewSource, fnCallback, bStandingRedraw) {
    // DataTables 1.10 compatibility - if 1.10 then `versionCheck` exists.
    // 1.10's API has ajax reloading built in, so we use those abilities
    // directly.
    if (jQuery.fn.dataTable.versionCheck) {
        var api = new jQuery.fn.dataTable.Api(oSettings);

        if (sNewSource) {
            api.ajax.url(sNewSource).load(fnCallback, !bStandingRedraw);
        }
        else {
            api.ajax.reload(fnCallback, !bStandingRedraw);
        }
        return;
    }

    if (sNewSource !== undefined && sNewSource !== null) {
        oSettings.sAjaxSource = sNewSource;
    }

    // Server-side processing should just call fnDraw
    if (oSettings.oFeatures.bServerSide) {
        this.fnDraw();
        return;
    }

    this.oApi._fnProcessingDisplay(oSettings, true);
    var that = this;
    var iStart = oSettings._iDisplayStart;
    var aData = [];

    this.oApi._fnServerParams(oSettings, aData);

    oSettings.fnServerData.call(oSettings.oInstance, oSettings.sAjaxSource, aData, function (json) {
        /* Clear the old information from the table */
        that.oApi._fnClearTable(oSettings);

        /* Got the data - add it to the table */
        var aData = (oSettings.sAjaxDataProp !== "") ?
			that.oApi._fnGetObjectDataFn(oSettings.sAjaxDataProp)(json) : json;

        for (var i = 0 ; i < aData.length ; i++) {
            that.oApi._fnAddData(oSettings, aData[i]);
        }

        oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();

        that.fnDraw();

        if (bStandingRedraw === true) {
            oSettings._iDisplayStart = iStart;
            that.oApi._fnCalculateEnd(oSettings);
            that.fnDraw(false);
        }

        that.oApi._fnProcessingDisplay(oSettings, false);

        /* Callback user function - for event handlers etc */
        if (typeof fnCallback == 'function' && fnCallback !== null) {
            fnCallback(oSettings);
        }
    }, oSettings);
};

/*!
 FixedHeader 3.1.0
 ©2009-2015 SpryMedia Ltd - datatables.net/license
*/
(function (d) { "function" === typeof define && define.amd ? define(["jquery", "datatables.net"], function (g) { return d(g, window, document) }) : "object" === typeof exports ? module.exports = function (g, h) { g || (g = window); if (!h || !h.fn.dataTable) h = require("datatables.net")(g, h).$; return d(h, g, g.document) } : d(jQuery, window, document) })(function (d, g, h, k) {
    var j = d.fn.dataTable, l = 0, i = function (b, a) {
        if (!(this instanceof i)) throw "FixedHeader must be initialised with the 'new' keyword."; !0 === a && (a = {}); b = new j.Api(b); this.c = d.extend(!0,
        {}, i.defaults, a); this.s = { dt: b, position: { theadTop: 0, tbodyTop: 0, tfootTop: 0, tfootBottom: 0, width: 0, left: 0, tfootHeight: 0, theadHeight: 0, windowHeight: d(g).height(), visible: !0 }, headerMode: null, footerMode: null, autoWidth: b.settings()[0].oFeatures.bAutoWidth, namespace: ".dtfc" + l++, scrollLeft: { header: -1, footer: -1 }, enable: !0 }; this.dom = {
            floatingHeader: null, thead: d(b.table().header()), tbody: d(b.table().body()), tfoot: d(b.table().footer()), header: { host: null, floating: null, placeholder: null }, footer: {
                host: null, floating: null,
                placeholder: null
            }
        }; this.dom.header.host = this.dom.thead.parent(); this.dom.footer.host = this.dom.tfoot.parent(); var e = b.settings()[0]; if (e._fixedHeader) throw "FixedHeader already initialised on table " + e.nTable.id; e._fixedHeader = this; this._constructor()
    }; d.extend(i.prototype, {
        enable: function (b) { this.s.enable = b; this.c.header && this._modeChange("in-place", "header", !0); this.c.footer && this.dom.tfoot.length && this._modeChange("in-place", "footer", !0); this.update() }, headerOffset: function (b) {
            b !== k && (this.c.headerOffset =
            b, this.update()); return this.c.headerOffset
        }, footerOffset: function (b) { b !== k && (this.c.footerOffset = b, this.update()); return this.c.footerOffset }, update: function () { this._positions(); this._scroll(!0) }, _constructor: function () {
            var b = this, a = this.s.dt; d(g).on("scroll" + this.s.namespace, function () { b._scroll() }).on("resize" + this.s.namespace, function () { b.s.position.windowHeight = d(g).height(); b.update() }); a.on("column-reorder.dt.dtfc column-visibility.dt.dtfc draw.dt.dtfc", function () { b.update() }); a.on("destroy.dtfc",
            function () { a.off(".dtfc"); d(g).off(b.s.namespace) }); this._positions(); this._scroll()
        }, _clone: function (b, a) {
            var e = this.s.dt, c = this.dom[b], f = "header" === b ? this.dom.thead : this.dom.tfoot; !a && c.floating ? c.floating.removeClass("fixedHeader-floating fixedHeader-locked") : (c.floating && (c.placeholder.remove(), c.floating.children().detach(), c.floating.remove()), c.floating = d(e.table().node().cloneNode(!1)).removeAttr("id").append(f).appendTo("body"), c.placeholder = f.clone(!1), c.host.append(c.placeholder), this._matchWidths(c.placeholder,
            c.floating))
        }, _matchWidths: function (b, a) { var e = function (c) { var f = d(c, b).map(function () { return d(this).width() }).toArray(); d(c, a).each(function (a) { d(this).width(f[a]).css("min-width", f[a]) }) }; e("th"); e("td") }, _unsize: function (b) { var a = this.dom[b].floating; a && ("footer" === b || "header" === b && !this.s.autoWidth) && d("th, td", a).css("width", "") }, _horizontal: function (b, a) { var e = this.dom[b], c = this.s.position, f = this.s.scrollLeft; e.floating && f[b] !== a && (e.floating.css("left", c.left - a), f[b] = a) }, _modeChange: function (b,
        a, e) {
            var c = this.dom[a], f = this.s.position; if ("in-place" === b) { if (c.placeholder && (c.placeholder.remove(), c.placeholder = null), this._unsize(a), c.host.append("header" === a ? this.dom.thead : this.dom.tfoot), c.floating) c.floating.remove(), c.floating = null } else "in" === b ? (this._clone(a, e), c.floating.addClass("fixedHeader-floating").css("header" === a ? "top" : "bottom", this.c[a + "Offset"]).css("left", f.left + "px").css("width", f.width + "px"), "footer" === a && c.floating.css("top", "")) : "below" === b ? (this._clone(a, e), c.floating.addClass("fixedHeader-locked").css("top",
            f.tfootTop - f.theadHeight).css("left", f.left + "px").css("width", f.width + "px")) : "above" === b && (this._clone(a, e), c.floating.addClass("fixedHeader-locked").css("top", f.tbodyTop).css("left", f.left + "px").css("width", f.width + "px")); this.s.scrollLeft.header = -1; this.s.scrollLeft.footer = -1; this.s[a + "Mode"] = b
        }, _positions: function () {
            var b = this.s.dt.table(), a = this.s.position, e = this.dom, b = d(b.node()), c = b.children("thead"), f = b.children("tfoot"), e = e.tbody; a.visible = b.is(":visible"); a.width = b.outerWidth(); a.left = b.offset().left;
            a.theadTop = c.offset().top; a.tbodyTop = e.offset().top; a.theadHeight = a.tbodyTop - a.theadTop; f.length ? (a.tfootTop = f.offset().top, a.tfootBottom = a.tfootTop + f.outerHeight(), a.tfootHeight = a.tfootBottom - a.tfootTop) : (a.tfootTop = a.tbodyTop + e.outerHeight(), a.tfootBottom = a.tfootTop, a.tfootHeight = a.tfootTop)
        }, _scroll: function (b) {
            var a = d(h).scrollTop(), e = d(h).scrollLeft(), c = this.s.position, f; if (this.s.enable && (this.c.header && (f = !c.visible || a <= c.theadTop - this.c.headerOffset ? "in-place" : a <= c.tfootTop - c.theadHeight -
            this.c.headerOffset ? "in" : "below", (b || f !== this.s.headerMode) && this._modeChange(f, "header", b), this._horizontal("header", e)), this.c.footer && this.dom.tfoot.length)) a = !c.visible || a + c.windowHeight >= c.tfootBottom + this.c.footerOffset ? "in-place" : c.windowHeight + a > c.tbodyTop + c.tfootHeight + this.c.footerOffset ? "in" : "above", (b || a !== this.s.footerMode) && this._modeChange(a, "footer", b), this._horizontal("footer", e)
        }
    }); i.version = "3.1.0"; i.defaults = { header: !0, footer: !1, headerOffset: 0, footerOffset: 0 }; d.fn.dataTable.FixedHeader =
    i; d.fn.DataTable.FixedHeader = i; d(h).on("init.dt.dtb", function (b, a) { if ("dt" === b.namespace) { var e = a.oInit.fixedHeader || j.defaults.fixedHeader; e && !a._fixedHeader && new i(a, e) } }); j.Api.register("fixedHeader()", function () { }); j.Api.register("fixedHeader.adjust()", function () { return this.iterator("table", function (b) { (b = b._fixedHeader) && b.update() }) }); j.Api.register("fixedHeader.enable()", function (b) { return this.iterator("table", function (a) { (a = a._fixedHeader) && a.enable(b !== k ? b : !0) }) }); j.Api.register("fixedHeader.disable()",
    function () { return this.iterator("table", function (b) { (b = b._fixedHeader) && b.enable(!1) }) }); d.each(["header", "footer"], function (b, a) { j.Api.register("fixedHeader." + a + "Offset()", function (b) { var c = this.context; return b === k ? c.length && c[0]._fixedHeader ? c[0]._fixedHeader[a + "Offset"]() : k : this.iterator("table", function (c) { if (c = c._fixedHeader) c[a + "Offset"](b) }) }) }); return i
});

